home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 748 / 748.xpi / content / browser.js < prev    next >
Text File  |  2010-02-11  |  21KB  |  672 lines

  1. // this file is the JavaScript backing for the UI wrangling which happens in
  2. // browser.xul. It also initializes the Greasemonkey singleton which contains
  3. // all the main injection logic, though that should probably be a proper XPCOM
  4. // service and wouldn't need to be initialized in that case.
  5.  
  6. var GM_BrowserUI = new Object();
  7.  
  8. /**
  9.  * nsISupports.QueryInterface
  10.  */
  11. GM_BrowserUI.QueryInterface = function(aIID) {
  12.   if (!aIID.equals(Components.interfaces.nsISupports) &&
  13.       !aIID.equals(Components.interfaces.gmIBrowserWindow) &&
  14.       !aIID.equals(Components.interfaces.nsISupportsWeakReference) &&
  15.       !aIID.equals(Components.interfaces.nsIWebProgressListener))
  16.     throw Components.results.NS_ERROR_NO_INTERFACE;
  17.  
  18.   return this;
  19. };
  20.  
  21.  
  22. /**
  23.  * Called when this file is parsed, by the last line. Set up initial objects,
  24.  * do version checking, and set up listeners for browser xul load and location
  25.  * changes.
  26.  */
  27. GM_BrowserUI.init = function() {
  28.   this.menuCommanders = [];
  29.   this.currentMenuCommander = null;
  30.  
  31.   GM_listen(window, "load", GM_hitch(this, "chromeLoad"));
  32.   GM_listen(window, "unload", GM_hitch(this, "chromeUnload"));
  33. };
  34.  
  35. /**
  36.  * The browser XUL has loaded. Find the elements we need and set up our
  37.  * listeners and wrapper objects.
  38.  */
  39. GM_BrowserUI.chromeLoad = function(e) {
  40.   // get all required DOM elements
  41.   this.tabBrowser = document.getElementById("content");
  42.   this.appContent = document.getElementById("appcontent");
  43.   this.sidebar = document.getElementById("sidebar");
  44.   this.contextMenu = document.getElementById("contentAreaContextMenu");
  45.   this.statusImage = document.getElementById("gm-status-image");
  46.   this.statusLabel = document.getElementById("gm-status-label");
  47.   this.statusPopup = document.getElementById("gm-status-popup");
  48.   this.statusEnabledItem = document.getElementById("gm-status-enabled-item");
  49.   this.generalMenuEnabledItem = document.getElementById("gm-general-menu-enabled-item");
  50.   this.toolsMenu = document.getElementById("menu_ToolsPopup");
  51.   this.bundle = document.getElementById("gm-browser-bundle");
  52.  
  53.   // seamonkey compat
  54.   if (!this.toolsMenu) {
  55.     this.toolsMenu = document.getElementById("taskPopup");
  56.   }
  57.  
  58.   // songbird compat
  59.   if (!this.appContent && this.tabBrowser) {
  60.     this.appContent = this.tabBrowser.parentNode;
  61.   }
  62.  
  63.   // update visual status when enabled state changes
  64.   this.enabledWatcher = GM_hitch(this, "refreshStatus");
  65.   GM_prefRoot.watch("enabled", this.enabledWatcher);
  66.  
  67.   // hook various events
  68.   GM_listen(this.appContent, "DOMContentLoaded", GM_hitch(this, "contentLoad"));
  69.   GM_listen(this.sidebar, "DOMContentLoaded", GM_hitch(this, "contentLoad"));
  70.   GM_listen(this.contextMenu, "popupshowing", GM_hitch(this, "contextMenuShowing"));
  71.   GM_listen(this.toolsMenu, "popupshowing", GM_hitch(this, "toolsMenuShowing"));
  72.  
  73.   // listen for clicks on the install bar
  74.   Components.classes["@mozilla.org/observer-service;1"]
  75.             .getService(Components.interfaces.nsIObserverService)
  76.             .addObserver(this, "install-userscript", true);
  77.  
  78.   // we use this to determine if we are the active window sometimes
  79.   this.winWat = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
  80.                           .getService(Components.interfaces.nsIWindowWatcher);
  81.  
  82.   // this gives us onLocationChange
  83.   this.tabBrowser.addProgressListener(this,
  84.     Components.interfaces.nsIWebProgress.NOTIFY_LOCATION);
  85.  
  86.   // update enabled icon
  87.   this.refreshStatus();
  88.  
  89.   // register for notifications from greasemonkey-service about ui type things
  90.   this.gmSvc = Components.classes["@greasemonkey.mozdev.org/greasemonkey-service;1"]
  91.                          .getService(Components.interfaces.gmIGreasemonkeyService);
  92.  
  93.   // reference this once, so that the getter is called at least once, and the
  94.   // initialization routines will run, no matter what
  95.   this.gmSvc.wrappedJSObject.config;
  96.   
  97.   this.gmSvc.registerBrowser(this);
  98. };
  99.  
  100. /**
  101.  * gmIBrowserWindow.registerMenuCommand
  102.  */
  103. GM_BrowserUI.registerMenuCommand = function(menuCommand) {
  104.   if (this.isMyWindow(menuCommand.window)) {
  105.     var commander = this.getCommander(menuCommand.window);
  106.  
  107.     commander.registerMenuCommand(menuCommand.name,
  108.                                   menuCommand.doCommand,
  109.                                   menuCommand.accelKey,
  110.                                   menuCommand.accelModifiers,
  111.                                   menuCommand.accessKey);
  112.   }
  113. };
  114.  
  115. /**
  116.  * gmIBrowserWindow.openInTab
  117.  */
  118. GM_BrowserUI.openInTab = function(domWindow, url) {
  119.   if (this.isMyWindow(domWindow)) {
  120.     this.tabBrowser.addTab(url);
  121.   }
  122. };
  123.  
  124. /**
  125.  * Gets called when a DOMContentLoaded event occurs somewhere in the browser.
  126.  * If that document is in in the top-level window of the focused tab, find
  127.  * it's menu items and activate them.
  128.  */
  129. GM_BrowserUI.contentLoad = function(e) {
  130.   var safeWin;
  131.   var unsafeWin;
  132.   var href;
  133.   var commander;
  134.  
  135.   if (!GM_getEnabled()) {
  136.     return;
  137.   }
  138.  
  139.   safeWin = e.target.defaultView;
  140.   unsafeWin = safeWin.wrappedJSObject;
  141.   href = safeWin.location.href;
  142.  
  143.   if (GM_isGreasemonkeyable(href)) {
  144.     commander = this.getCommander(unsafeWin);
  145.  
  146.     // if this content load is in the focused tab, attach the menuCommaander
  147.     if (unsafeWin == this.tabBrowser.selectedBrowser.contentWindow) {
  148.       this.currentMenuCommander = commander;
  149.       this.currentMenuCommander.attach();
  150.     }
  151.  
  152.     this.gmSvc.domContentLoaded({ wrappedJSObject: unsafeWin }, window);
  153.  
  154.     GM_listen(unsafeWin, "pagehide", GM_hitch(this, "contentUnload"));
  155.   }
  156.  
  157.   // Show the greasemonkey install banner if we are navigating to a .user.js
  158.   // file in a top-level tab.  If the file was previously cached it might have
  159.   // been given a number after .user, like gmScript.user-12.js
  160.   if (href.match(/\.user(?:-\d+)?\.js$/) && safeWin == safeWin.top) {
  161.     var browser = this.tabBrowser.getBrowserForDocument(safeWin.document);
  162.     this.showInstallBanner(browser);
  163.   }
  164. };
  165.  
  166.  
  167. /**
  168.  * Shows the install banner across the top of the tab that is displayed when
  169.  * a user selects "show script source" in the install dialog.
  170.  */
  171. GM_BrowserUI.showInstallBanner = function(browser) {
  172.   var greeting = this.bundle.getString("greeting.msg");
  173.  
  174.   if (this.tabBrowser.showMessage) {
  175.     // Firefox 1.5 and lower
  176.     this.tabBrowser.showMessage(
  177.       browser,
  178.       "chrome://greasemonkey/content/icon_small.png",
  179.       greeting,
  180.       this.bundle.getString("greeting.btn"),
  181.       null /* default doc shell */,
  182.       "install-userscript",
  183.       null /* no popuup */,
  184.       "top",
  185.       true /* show close button */,
  186.       this.bundle.getString("greeting.btnAccess") /* access key */);
  187.   } else {
  188.     // Firefox 2.0+
  189.     var notificationBox = this.tabBrowser.getNotificationBox(browser);
  190.  
  191.     // Remove existing notifications. Notifications get removed
  192.     // automatically onclick and on page navigation, but we need to remove
  193.     // them ourselves in the case of reload, or they stack up.
  194.     for (var i = 0, child; child = notificationBox.childNodes[i]; i++) {
  195.       if (child.getAttribute("value") == "install-userscript") {
  196.         notificationBox.removeNotification(child);
  197.       }
  198.     }
  199.  
  200.     var notification = notificationBox.appendNotification(
  201.       greeting,
  202.       "install-userscript",
  203.       "chrome://greasemonkey/content/icon_small.png",
  204.       notificationBox.PRIORITY_WARNING_MEDIUM,
  205.       [{
  206.         label: this.bundle.getString("greeting.btn"),
  207.         accessKey: this.bundle.getString("greeting.btnAccess"),
  208.         popup: null,
  209.         callback: GM_hitch(this, "installCurrentScript")
  210.       }]
  211.     );
  212.   }
  213. };
  214.  
  215. /**
  216.  * Called from greasemonkey service when we should load a user script.
  217.  */
  218. GM_BrowserUI.startInstallScript = function(uri, timer) {
  219.   if (!timer) {
  220.     // docs for nsicontentpolicy say we're not supposed to block, so short
  221.     // timer.
  222.     window.setTimeout(
  223.       function() { GM_BrowserUI.startInstallScript(uri, true) }, 0);
  224.  
  225.     return;
  226.   }
  227.  
  228.   this.scriptDownloader_ = new GM_ScriptDownloader(window, uri, this.bundle);
  229.   this.scriptDownloader_.startInstall();
  230. };
  231.  
  232.  
  233. /**
  234.  * Open the tab to show the contents of a script and display the banner to let
  235.  * the user install it.
  236.  */
  237. GM_BrowserUI.showScriptView = function(scriptDownloader) {
  238.   this.scriptDownloader_ = scriptDownloader;
  239.  
  240.   var tab = this.tabBrowser.addTab(scriptDownloader.script.previewURL);
  241.   var browser = this.tabBrowser.getBrowserForTab(tab);
  242.  
  243.   this.tabBrowser.selectedTab = tab;
  244. };
  245.  
  246. /**
  247.  * Implements nsIObserve.observe. Right now we're only observing our own
  248.  * install-userscript, which happens when the install bar is clicked.
  249.  */
  250. GM_BrowserUI.observe = function(subject, topic, data) {
  251.   if (topic == "install-userscript") {
  252.     if (window == this.winWat.activeWindow) {
  253.       this.installCurrentScript();
  254.     }
  255.   } else {
  256.     throw new Error("Unexpected topic received: {" + topic + "}");
  257.   }
  258. };
  259.  
  260. /**
  261.  * Handles the install button getting clicked.
  262.  */
  263. GM_BrowserUI.installCurrentScript = function() {
  264.   this.scriptDownloader_.installScript();
  265. };
  266.  
  267. GM_BrowserUI.installScript = function(script){
  268.   GM_getConfig().install(script);
  269.   this.showHorrayMessage(script.name);
  270. };
  271.  
  272. /**
  273.  * The browser's location has changed. Usually, we don't care. But in the case
  274.  * of tab switching we need to change the list of commands displayed in the
  275.  * User Script Commands submenu.
  276.  */
  277. GM_BrowserUI.onLocationChange = function(a,b,c) {
  278.   if (this.currentMenuCommander != null) {
  279.     this.currentMenuCommander.detach();
  280.     this.currentMenuCommander = null;
  281.   }
  282.  
  283.   var menuCommander = this.getCommander(this.tabBrowser.selectedBrowser.
  284.                                         contentWindow);
  285.  
  286.   if (menuCommander) {
  287.     this.currentMenuCommander = menuCommander;
  288.     this.currentMenuCommander.attach();
  289.   }
  290. };
  291.  
  292. /**
  293.  * A content document has unloaded. We need to remove it's menuCommander to
  294.  * avoid leaking it's memory.
  295.  */
  296. GM_BrowserUI.contentUnload = function(e) {
  297.   if (e.persisted) {
  298.     return;
  299.   }
  300.  
  301.   var unsafeWin = e.target.defaultView;
  302.  
  303.   // remove the commander for this document
  304.   var commander = null;
  305.  
  306.   // looping over commanders rather than using getCommander because we need
  307.   // the index into commanders.splice.
  308.   for (var i = 0; item = this.menuCommanders[i]; i++) {
  309.     if (item.win == unsafeWin) {
  310.  
  311.       if (item.commander == this.currentMenuCommander) {
  312.         this.currentMenuCommander.detach();
  313.         this.currentMenuCommander = null;
  314.       }
  315.  
  316.       this.menuCommanders.splice(i, 1);
  317.  
  318.       break;
  319.     }
  320.   }
  321. };
  322.  
  323. /**
  324.  * The browser XUL has unloaded. We need to let go of the pref watcher so
  325.  * that a non-existant window is not informed when greasemonkey enabled state
  326.  * changes. And we need to let go of the progress listener so that we don't
  327.  * leak it's memory.
  328.  */
  329. GM_BrowserUI.chromeUnload = function() {
  330.   GM_prefRoot.unwatch("enabled", this.enabledWatcher);
  331.   this.tabBrowser.removeProgressListener(this);
  332.   this.gmSvc.unregisterBrowser(this);
  333.   delete this.menuCommanders;
  334. };
  335.  
  336. /**
  337.  * Called when the content area context menu is showing. We figure out whether
  338.  * to show our context items.
  339.  */
  340. GM_BrowserUI.contextMenuShowing = function() {
  341.   var contextItem = ge("view-userscript");
  342.   var contextSep = ge("install-userscript-sep");
  343.  
  344.   var culprit = document.popupNode;
  345.  
  346.   while (culprit && culprit.tagName && culprit.tagName.toLowerCase() != "a") {
  347.      culprit = culprit.parentNode;
  348.   }
  349.  
  350.   contextItem.hidden =
  351.     contextSep.hidden =
  352.     !this.getUserScriptLinkUnderPointer();
  353. };
  354.  
  355.  
  356. GM_BrowserUI.getUserScriptLinkUnderPointer = function() {
  357.   var culprit = document.popupNode;
  358.  
  359.   while (culprit && culprit.tagName && culprit.tagName.toLowerCase() != "a") {
  360.      culprit = culprit.parentNode;
  361.   }
  362.  
  363.   if (!culprit || !culprit.href ||
  364.       !culprit.href.match(/\.user\.js(\?|$)/i)) {
  365.     return null;
  366.   }
  367.  
  368.   var ioSvc = Components.classes["@mozilla.org/network/io-service;1"]
  369.                         .getService(Components.interfaces.nsIIOService);
  370.   var uri = ioSvc.newURI(culprit.href, null, null);
  371.  
  372.   return uri;
  373. };
  374.  
  375. GM_BrowserUI.toolsMenuShowing = function() {
  376.   var installItem = ge("userscript-tools-install");
  377.   var hidden = true;
  378.  
  379.   if (window._content && window._content.location &&
  380.       window.content.location.href.match(/\.user\.js(\?|$)/i)) {
  381.     hidden = false;
  382.   }
  383.  
  384.   // Better to use hidden than collapsed because collapsed still allows you to
  385.   // select the item using keyboard navigation, but hidden doesn't.
  386.   installItem.setAttribute("hidden", hidden.toString());
  387. };
  388.  
  389.  
  390. /**
  391.  * Helper method which gets the menuCommander corresponding to a given
  392.  * document
  393.  */
  394. GM_BrowserUI.getCommander = function(unsafeWin) {
  395.   for (var i = 0; i < this.menuCommanders.length; i++) {
  396.     if (this.menuCommanders[i].win == unsafeWin) {
  397.       return this.menuCommanders[i].commander;
  398.     }
  399.   }
  400.  
  401.   // no commander found. create one and add it.
  402.   var commander = new GM_MenuCommander(document);
  403.   this.menuCommanders.push({win:unsafeWin, commander:commander});
  404.  
  405.   return commander;
  406. };
  407.  
  408. /**
  409.  * Helper to determine if a given dom window is in this tabbrowser
  410.  */
  411. GM_BrowserUI.isMyWindow = function(domWindow) {
  412.   var tabbrowser = getBrowser();
  413.   var browser;
  414.  
  415.   for (var i = 0; browser = tabbrowser.browsers[i]; i++) {
  416.     if (browser.contentWindow == domWindow) {
  417.       return true;
  418.     }
  419.   }
  420.  
  421.   return false;
  422. };
  423.  
  424. function GM_showGeneralPopup(aEvent) {
  425.   // set the enabled/disabled state
  426.   GM_BrowserUI.generalMenuEnabledItem.setAttribute("checked", GM_getEnabled());
  427. }
  428.  
  429. function GM_showPopup(aEvent) {
  430.   function urlsOfAllFrames(contentWindow) {
  431.     function collect(contentWindow) {
  432.       urls = urls.concat(urlsOfAllFrames(contentWindow));
  433.     }
  434.     var urls = [contentWindow.location.href];
  435.     Array.prototype.slice.call(contentWindow.frames).forEach(collect);
  436.     return urls;
  437.   }
  438.  
  439.   function uniq(a) {
  440.     var seen = {}, list = [], item;
  441.     for (var i = 0; i < a.length; i++) {
  442.       item = a[i];
  443.       if (!seen.hasOwnProperty(item))
  444.         seen[item] = list.push(item);
  445.     }
  446.     return list;
  447.   }
  448.  
  449.   function scriptsMatching(urls) {
  450.  
  451.     function testMatchURLs(script) {
  452.  
  453.       function testMatchURL(url) {
  454.         return script.matchesURL(url);
  455.       }
  456.  
  457.       return urls.some(testMatchURL);
  458.     }
  459.  
  460.     return GM_getConfig().getMatchingScripts(testMatchURLs);
  461.   }
  462.  
  463.   function appendScriptToPopup(script) {
  464.     var mi = document.createElement("menuitem");
  465.     mi.setAttribute("label", script.name);
  466.     mi.script = script;
  467.     mi.setAttribute("type", "checkbox");
  468.     mi.setAttribute("checked", script.enabled.toString());
  469.     popup.insertBefore(mi, tail);
  470.   }
  471.  
  472.   var popup = aEvent.target;
  473.   var tail = document.getElementById("gm-status-no-scripts-sep");
  474.  
  475.   // set the enabled/disabled state
  476.   GM_BrowserUI.statusEnabledItem.setAttribute("checked", GM_getEnabled());
  477.  
  478.   // remove all the scripts from the list
  479.   for (var i = popup.childNodes.length - 1; i >= 0; i--) {
  480.     var node = popup.childNodes[i];
  481.     if (node.script || node.getAttribute("value") == "hack") {
  482.       popup.removeChild(node);
  483.     }
  484.   }
  485.  
  486.   var urls = uniq( urlsOfAllFrames( getBrowser().contentWindow ));
  487.   var runsOnTop = scriptsMatching( [urls.shift()] ); // first url = top window
  488.   var runsFramed = scriptsMatching( urls ); // remainder are all its subframes
  489.  
  490.   // drop all runsFramed scripts already present in runsOnTop
  491.   for (var i = 0; i < runsOnTop.length; i++) {
  492.     var j = 0, item = runsOnTop[i];
  493.     while (j < runsFramed.length) {
  494.       if (item === runsFramed[j]) {
  495.         runsFramed.splice(j, 1);
  496.       } else {
  497.         j++;
  498.       }
  499.     }
  500.   }
  501.  
  502.   // build the new list of scripts
  503.   if (runsFramed.length) {
  504.     runsFramed.forEach(appendScriptToPopup);
  505.     if (runsOnTop.length) { // only add the separator if there is stuff below
  506.       var separator = document.createElement("menuseparator");
  507.       separator.setAttribute("value", "hack"); // remove it in the loop above
  508.       popup.insertBefore(separator, tail);
  509.     }
  510.   }
  511.   runsOnTop.forEach(appendScriptToPopup);
  512.  
  513.   var foundInjectedScript = !!(runsFramed.length + runsOnTop.length);
  514.   document.getElementById("gm-status-no-scripts").collapsed = foundInjectedScript;
  515. }
  516.  
  517. /**
  518.  * Handle clicking one of the items in the popup. Left-click toggles the enabled
  519.  * state, rihgt-click opens in an editor.
  520.  */
  521. function GM_popupClicked(aEvent) {
  522.   if (aEvent.button == 0 || aEvent.button == 2) {
  523.     var script = aEvent.target.script;
  524.     if (!script) return;
  525.  
  526.     if (aEvent.button == 0) // left-click: toggle enabled state
  527.       script.enabled =! script.enabled;
  528.     else // right-click: open in editor
  529.       openInEditor(script);
  530.  
  531.     closeMenus(aEvent.target);
  532.   }
  533. }
  534.  
  535. /**
  536.  * Greasemonkey's enabled state has changed, either as a result of clicking
  537.  * the icon in this window, clicking it in another window, or even changing
  538.  * the mozilla preference that backs it directly.
  539.  */
  540. GM_BrowserUI.refreshStatus = function() {
  541.   if (GM_getEnabled()) {
  542.     this.statusImage.src = "chrome://greasemonkey/content/icon_small.png";
  543.     this.statusImage.tooltipText = this.bundle.getString("tooltip.enabled");
  544.   } else {
  545.     this.statusImage.src = "chrome://greasemonkey/content/icon_small_disabled.png";
  546.     this.statusImage.tooltipText = this.bundle.getString("tooltip.disabled");
  547.   }
  548.  
  549.   this.statusImage.style.opacity = "1.0";
  550. };
  551.  
  552. GM_BrowserUI.newUserScript = function() {
  553.   var windowWatcher = Components
  554.     .classes["@mozilla.org/embedcomp/window-watcher;1"]
  555.     .getService(Components.interfaces.nsIWindowWatcher);
  556.   windowWatcher.openWindow(
  557.     window, "chrome://greasemonkey/content/newscript.xul", null,
  558.     "chrome,dependent,centerscreen,resizable,dialog", null
  559.   );
  560. };
  561.  
  562. GM_BrowserUI.showStatus = function(message, autoHide) {
  563.   if (this.statusLabel.collapsed) {
  564.     this.statusLabel.collapsed = false;
  565.   }
  566.  
  567.   message += " ";
  568.  
  569.   var box = document.createElement("vbox");
  570.   var label = document.createElement("label");
  571.   box.style.position = "fixed";
  572.   box.style.left = "-10000px";
  573.   box.style.top = "-10000px";
  574.   box.style.border = "5px solid red";
  575.   box.appendChild(label);
  576.   document.documentElement.appendChild(box);
  577.   label.setAttribute("value", message);
  578.  
  579.   var current = parseInt(this.statusLabel.style.width);
  580.   this.statusLabel.value = message;
  581.   var max = label.boxObject.width;
  582.  
  583.   this.showAnimation = new Accelimation(this.statusLabel.style,
  584.                                           "width", max, 300, 2, "px");
  585.   this.showAnimation.onend = GM_hitch(this, "showStatusAnimationEnd", autoHide);
  586.   this.showAnimation.start();
  587. };
  588.  
  589. GM_BrowserUI.showStatusAnimationEnd = function(autoHide) {
  590.   this.showAnimation = null;
  591.  
  592.   if (autoHide) {
  593.     this.setAutoHideTimer();
  594.   }
  595. };
  596.  
  597. GM_BrowserUI.setAutoHideTimer = function() {
  598.   if (this.autoHideTimer) {
  599.     window.clearTimeout(this.autoHideTimer);
  600.   }
  601.  
  602.   this.autoHideTimer = window.setTimeout(GM_hitch(this, "hideStatus"), 3000);
  603. };
  604.  
  605. GM_BrowserUI.hideStatusImmediately = function() {
  606.   if (this.showAnimation) {
  607.     this.showAnimation.stop();
  608.     this.showAnimation = null;
  609.   }
  610.  
  611.   if (this.hideAnimation) {
  612.     this.hideAnimation.stop();
  613.     this.hideAnimation = null;
  614.   }
  615.  
  616.   if (this.autoHideTimer) {
  617.     window.clearTimeout(this.autoHideTimer);
  618.     this.autoHideTimer = null;
  619.   }
  620.  
  621.   this.statusLabel.style.width = "0";
  622.   this.statusLabel.collapsed = true;
  623. };
  624.  
  625. GM_BrowserUI.hideStatus = function() {
  626.   if (!this.hideAnimation) {
  627.     this.autoHideTimer = null;
  628.     this.hideAnimation = new Accelimation(this.statusLabel.style,
  629.                                             "width", 0, 300, 2, "px");
  630.     this.hideAnimation.onend = GM_hitch(this, "hideStatusAnimationEnd");
  631.     this.hideAnimation.start();
  632.   }
  633. };
  634.  
  635. GM_BrowserUI.hideStatusAnimationEnd = function() {
  636.   this.hideAnimation = null;
  637.   this.statusLabel.collapsed = true;
  638. };
  639.  
  640. // necessary for webProgressListener implementation
  641. GM_BrowserUI.onProgressChange = function(webProgress,b,c,d,e,f){};
  642. GM_BrowserUI.onStateChange = function(a,b,c,d){};
  643. GM_BrowserUI.onStatusChange = function(a,b,c,d){};
  644. GM_BrowserUI.onSecurityChange = function(a,b,c){};
  645. GM_BrowserUI.onLinkIconAvailable = function(a){};
  646.  
  647. GM_BrowserUI.showHorrayMessage = function(scriptName) {
  648.   this.showStatus("'" + scriptName + "' " + this.bundle.getString("statusbar.installed"), true);
  649. };
  650.  
  651. GM_BrowserUI.installMenuItemClicked = function() {
  652.   GM_BrowserUI.startInstallScript(
  653.     gBrowser.currentURI
  654.   );
  655. };
  656.  
  657. GM_BrowserUI.viewContextItemClicked = function() {
  658.   var uri = GM_BrowserUI.getUserScriptLinkUnderPointer();
  659.  
  660.   this.scriptDownloader_ = new ScriptDownloader(window, uri, this.bundle);
  661.   this.scriptDownloader_.startViewScript();
  662. };
  663.  
  664. GM_BrowserUI.manageMenuItemClicked = function() {
  665.    GM_openUserScriptManager();
  666. };
  667.  
  668. //loggify(GM_BrowserUI, "GM_BrowserUI");
  669.  
  670. log("calling init...");
  671. GM_BrowserUI.init();
  672.